//////////////////////////////////////////////////////////////////////
//  Jack McCaffery
//  11-10-2014
//////////////////////////////////////////////////////////////////////

#pragma once

#include "Eigen/Core"

#include <QString>


template <class SC>
class BasicData;

/// \brief Helper class to allow multiple subscripting
///	   SC is the scalar type of the matrix data
template <class SC>
class ScriptHelper
{
public:
	/// \brief Constructor
	/// \param container_ Container of data to return
	/// \param i_ First index of the array access
	ScriptHelper (BasicData<SC> &container_, int i_);

	/// \brief Accessor operator
	/// \param j_ Second index of array access
	SC &operator[] (int j_);

private:
	/// \brief Storage for first index of array access
	int index;

	/// \brief Container for array data to access
	BasicData<SC> &container;
};

/// \brief Const helper class to allow multiple subscripting
///	   SC is the scalar type of the matrix data
template <class SC>
class ConstScriptHelper
{
public:
	/// \brief Constructor
	/// \param container_ Container of data to return
	/// \param i_ First index of the array access
	ConstScriptHelper (BasicData<SC> const &container_, int i_);

	/// \brief Accessor operator
	/// \param j_ Second index of array access
	SC operator[] (int j_) const;

private:
	/// \brief Storage for first index of array access
	int index;

	/// \brief Container for array data to access
	BasicData<SC> const &container;
};

///////////////////////////////////////////////////////////////////////////

/// \brief Simple class to contain array data
///	   SC is the scalar type of the matrix data
template <class SC>
class BasicData
{
public:
	~BasicData ();
	BasicData ();

	/// \brief Load basic data from file
	/// \param filename_ Name of file to load from
	bool load (QString const filename_);

	/// \brief Save basic data to file
	/// \param filename_ Name of file to save to
	bool save (QString const filename_) const;

	/// \brief Data accessor
	Eigen::Matrix<SC, Eigen::Dynamic, Eigen::Dynamic>
		const &getData() const;

	/// \brief Data accessor
	Eigen::Matrix<SC, Eigen::Dynamic, Eigen::Dynamic>
		&getData();

	/// \brief Equality operator
	/// \param other_ Object to compare against
	bool operator== (BasicData<SC> const &other_) const;

	/// \brief Inequality operator
	/// \param other_ Object to compare against
	bool operator!= (BasicData<SC> const &other_) const;

	/// \brief Element-wise accessor of data
	/// \param i_ Row index
	ScriptHelper<SC> operator[] (int i_);

	/// \brief Element-wise accessor of data (const)
	/// \param i_ Row index
	ConstScriptHelper<SC> operator[] (int i_) const;

protected:
	/// \brief Load additional, subclass specific data
	/// \param ifile File ptr pointing to the spot immediately after
	///		 the data loaded by load.
	virtual bool _load (FILE *ifile)
	{ Q_UNUSED (ifile); return true; }

	/// \brief Save additional, subclass specific data
	/// \param ifile File ptr pointing to the spot immediately after
	///		 the data saved by save.
	virtual bool _save (FILE *ofile) const
	{ Q_UNUSED (ofile); return true; }

	/// \brief Matrix of data values
	Eigen::Matrix<SC, Eigen::Dynamic, Eigen::Dynamic> data;
};
